'''
2;[[[1.92, 1.48], [0.67, -1.23], [0.35, -0.68]], [[-1.11,0.09], [-0.3, -0.39], [-0.59,-0.06]]]; [[1.0,1.0],[2.0,2.0]];[[1.0, 1.0], [2.0, 2.0]];[[1.0, 1.0], [2.0, 2.0]];[[1.0, 1.0], [2.0, 2.0]]
[[[14.64, 14.64], [-5.37, -5.37], [-4.62, -4.62]], [[-2.79, -2.79], [-3.03, -3.03], [-2.77,-2.77]]]
'''

import sys
import re
import ast
import numpy as np

def parse_array(segment):
    s = segment.strip()
    s = s.replace('（', '(').replace('）', ')').replace('，', ',')
    s = s.replace('(', '[').replace(')', ']')
    s = re.sub(r'\s+', ' ', s)
    return np.array(ast.literal_eval(s), dtype=float)

def ensure_3d(x):
    if x.ndim == 2:
        return x[np.newaxis, ...]
    if x.ndim == 3:
        return x
    raise ValueError("X/Q/K/V must be 2D or 3D")

def split_heads(x, num_heads):
    B, T, D = x.shape
    if D % num_heads != 0:
        raise ValueError("d_model must be divisible by num_heads")
    d_k = D // num_heads
    x = x.reshape(B, T, num_heads, d_k)
    return np.transpose(x, (0, 2, 1, 3))  # [B,H,T,d_k]

def combine_heads(x):
    B, H, T, d_k = x.shape
    return np.transpose(x, (0, 2, 1, 3)).reshape(B, T, H * d_k)  # [B,T,D]

def masked_softmax(scores):
    m = np.max(scores, axis=-1, keepdims=True)
    exp_scores = np.exp(scores - m)
    denom = np.sum(exp_scores, axis=-1, keepdims=True)
    return exp_scores / denom

def causal_mask(B, H, T):
    mask = np.tril(np.ones((T, T), dtype=bool))
    return np.broadcast_to(mask, (B, H, T, T))

def main():
    raw = sys.stdin.read().strip()
    if not raw:
        print([])
        return

    parts = re.split(r'\s*[:;]\s*', raw)
    parts = [p for p in parts if p != '']
    if len(parts) not in (5, 6):
        parts = re.split(r'\s*[:;]\s*', " ".join(raw.split()))
        parts = [p for p in parts if p != '']
    if len(parts) not in (5, 6):
        raise ValueError("Expect 5 parts (num_heads;Q;K;V;Wo) or 6 parts (num_heads;X;Wq;Wk;Wv;Wo)")

    num_heads = int(parts[0])

    if len(parts) == 6:
        X  = ensure_3d(parse_array(parts[1]))  # [B,T,D]
        Wq = parse_array(parts[2])             # [D,D]
        Wk = parse_array(parts[3])             # [D,D]
        Wv = parse_array(parts[4])             # [D,D]
        Wo = parse_array(parts[5])             # [D,D]
        D = X.shape[-1]
        if not (Wq.shape == Wk.shape == Wv.shape == Wo.shape == (D, D)):
            raise ValueError("Weights must be [d_model, d_model] and match X")
        Q = X @ Wq
        K = X @ Wk
        V = X @ Wv
    else:
        Q = ensure_3d(parse_array(parts[1]))
        K = ensure_3d(parse_array(parts[2]))
        V = ensure_3d(parse_array(parts[3]))
        Wo = parse_array(parts[4])
        if Wo.ndim != 2 or Wo.shape[0] != Wo.shape[1] or Wo.shape[0] != Q.shape[-1]:
            raise ValueError("Wo must be [d_model, d_model]")

    if Q.shape != K.shape or Q.shape != V.shape:
        raise ValueError("Q, K, V must share the same [B,T,D] shape")

    # Split heads
    Qh = split_heads(Q, num_heads)  # [B,H,T,d_k]
    Kh = split_heads(K, num_heads)
    Vh = split_heads(V, num_heads)
    B, H, T, d_k = Qh.shape

    # Scaled dot-product attention with causal mask
    scores = np.matmul(Qh, np.transpose(Kh, (0, 1, 3, 2))) / np.sqrt(d_k)  # [B,H,T,T]
    mask = causal_mask(B, H, T)  # allow <= current position
    scores = np.where(mask, scores, -1e9)

    attn = masked_softmax(scores)     # [B,H,T,T]
    out_heads = np.matmul(attn, Vh)   # [B,H,T,d_k]
    out = combine_heads(out_heads)    # [B,T,D]
    out = np.matmul(out, Wo)          # [B,T,D]

    out = np.around(out, 2).tolist()
    print(out)

if __name__ == "__main__":
    main()